package top.surgeqi.security.jwt.config.extend;

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import top.surgeqi.security.jwt.config.JwtTokenService;
import top.surgeqi.security.jwt.contants.AuthConstants;
import top.surgeqi.security.jwt.exception.CustomerAuthenticationException;

/**
 * <p><em>Created by qipp on 2020/2/28 16:01</em></p>
 * 刷新token认证器
 *
 * @author <a href="https://gitee.com/qipengpai">qipp</a>
 * @since 1.0.1
 */
@Component
public class RefreshTokenAuthenticator extends AbstractPrepareExtendAuthenticator {

    /**
     * 刷新token
     */
    private final static String AUTH_TYPE = "refresh_token";

    /**
     * 令牌相关操作Service
     */
    private final JwtTokenService jwtTokenService;

    public RefreshTokenAuthenticator(JwtTokenService jwtTokenService) {
        this.jwtTokenService = jwtTokenService;
    }

    /**
     * 刷新token时进行认证
     * <p>为获取Authentication 对象.</p>
     *
     * @param entity 集成认证实体
     * @return org.surge.oauth2common.model.UserAccount
     * @author qipp
     */
    @Override
    public UserDetails authenticate(ExtendAuthenticationEntity entity) {
        // 获取刷新令牌
        String refreshToken = entity.getAuthParameter(AuthConstants.AUTH_REFRESH_TOKEN);

        // 刷新令牌为空
        if (StringUtils.isEmpty(refreshToken)) {
            throw new CustomerAuthenticationException("刷新令牌为空！");
        }
        // 从刷新token中获取用户名
        String username = jwtTokenService.getSubjectFromRefreshToken(refreshToken);

        // 根据用户名查询用户账户
        UserDetails userAccount = abstractUserDetailsService.selectByUserName(username);
        if (null == userAccount) {
            throw new CustomerAuthenticationException("用户不存在！");
        }
        // 验证用户可用性并组合用户账户对象与角色权限
        return this.validateAndComposeUser(userAccount);
    }

    /**
     * 刷新token方式
     * {@inheritDoc}
     */
    @Override
    public boolean support(ExtendAuthenticationEntity entity) {
        return AUTH_TYPE.equals(entity.getAuthType());
    }
}
